<?php

namespace app\admin\model;

use app\common\model\TimeModel;
use app\common\service\redis\RedisQueueService;
use think\facade\Queue;
use think\Model;

/**
 * Class CashcardUser
 * @package app\admin\model
 * Author FashionJune
 */
class CashcardUser extends TimeModel
{

    protected $name = "cashcard_user";

    public function cate()
    {
        return $this->belongsTo('app\admin\model\CashcardCate', 'cate_id', 'id');
    }

    public function admin()
    {
        return $this->belongsTo('app\admin\model\SystemAdmin', 'to_admin', 'id');
    }

    public function user()
    {
        return $this->belongsTo('app\admin\model\UserBase', 'to_user', 'id');
    }


    /**
     * @title 读取自动处理
     * @author FashionJune
     */
    public static function onAfterRead(Model $model)
    {
        //过期时间
        if (isset($model->expire_time)) {
            $model->expire_at = date('Y-m-d H:i:s', $model->expire_time);
        }
        if (isset($model->send_time)) {
            $model->send_at = date('Y-m-d H:i:s', $model->send_time);
        }
        $model->status_info = self::getStatus($model->status, true);
        //分类名称
//        if (isset($model->cate->card_type)) {
//            $model->type_name = CashcardCate::getCardType()[$model->cate->card_type];
//        }

        //使用范围
        if ($model->related_cate) {
            $map_cate = [
                'id' => str2arr($model->related_cate)
            ];
            $cate_list = arr2str(ShopCate::where($map_cate)->cache()->column('title'));
        } else {
            $cate_list = '全场通用';
        }
        $model->cate_list = $cate_list;
    }


    /**
     * @param string $status
     * @param bool $color
     * @return string|string[]
     * @author FashionJune
     * @title 获取代金券状态
     */
    public static function getStatus($status = 'all', $color = false)
    {
        $arr = [-2 => '已使用', -1 => '已过期', 0 => '待使用', 1 => '使用中'];
        $color = [-2 => 'red', -1 => 'grey', 0 => 'green', 1 => 'orange'];
        if ($status === 'all') {
            return $arr;
        } elseif ($color) {
            return ($arr[$status]) ? '<span style="color:' . $color[$status] . '" >' . $arr[$status] . '</span>' : '';
        } else {
            return ($arr[$status]) ?? '';
        }
    }

    /**
     * @title 获取编码
     * @author FashionJune
     */
    public function getCashCardCode()
    {
        return substr(md5(random_int(100000, 999999) . md5(time())), 0, 16);
    }


    /**
     * @title 添加优惠券
     * @param CashcardCate $cate
     * @author FashionJune
     */
    public function addCashCards(CashcardCate $cate)
    {
        $insert_data = [];
        for ($i = 1; $i <= $cate->num; $i++) {
            $insert_data[] = [
                'cate_id' => $cate->id,
                'code' => $this->getCashCardCode(),
                'related_cate' => $cate->related_cate ?? '',
                'related_store' => $cate->related_store ?? '',
                'expire_time' => $cate->expire_time ?? (time() + 8640000)
            ];
        }
        $this->saveAll($insert_data);
    }


    /**
     * @title 获取会员卡券包拥有的所有类型
     * @param $user_id
     * @author FashionJune
     */
    public function getUserPackage($user_id)
    {
        $map = [
            ['to_user', '=', $user_id],
            ['status', '=', 1],
//            ['related_cate', '>', 0]
        ];
        $cate = $this->where($map)->column('related_cate');
        return array_unique($cate);
    }

    /**
     * @title 发放卡券
     * @param int $admin_id
     * @param int $user_id
     * @param int $cate_id
     * @return array
     * @author FashionJune
     */
    public function sendCardByAdmin(int $admin_id, int $user_id, int $cate_id)
    {
        $cate_info = CashcardCate::find($cate_id);
        //验证权限
        if (!in_array($admin_id, str2arr($cate_info->card_author))) {
            return error('您没有发放该卡券的权限');
        }
        //验证余量
        if (!$cate_info || $cate_info->rest_num < 1) {
            return error('该卡券剩余数量不足');
        }
        $map_user = [
            ['cate_id', '=', $cate_id],
            ['to_admin', '=', $admin_id],
            ['to_user', '>', 0],
        ];
        //验证额度
        $send_history_num = CashcardUser::where($map_user)->select();
        if ($send_history_num >= $cate_info->num_person) {
            return error('您在本卡券的发放额度已达上限');
        }
        //开始发放(暂时用数据库行级锁来处理并发，后续高并发可以考虑写入redis队列执行)
//        $send_queue = [
//            'cate_id' => $cate_info['id'],
//            'user_id' => $user_id,
//            'admin_id' => $admin_id,
//            'send_time' => time()
//        ];
//        RedisQueueService::init()->lpush('card_to_send', $send_queue);
        //数据库更新
        $update_data = [
            'status' => 1,
            'send_time' => time(),
            'to_admin' => $admin_id,
            'to_user' => $user_id
        ];
        $this->startTrans();
        try {
            $map_card = [
                ['to_user', '=', 0],
                ['status', '=', 0]
            ];
            $card = $this->where($map_card)->lock(true)->find();
            $card->save($update_data);
            $this->commit();
        } catch (\Exception $e) {
            $this->rollback();
            return error('操作失败，请刷新重试');
        }

    }

    /**
     * @title 检查是否可用
     * @param int $card_id
     * @param $store_cate
     * @param mixed $user_id
     * @author FashionJune
     */
    public function isAvailable(int $card_id, $store_cate,  $user_id = false)
    {
        $card_info = $this->withJoin('cate')->find($card_id);
        if (($card_info['expire_time'] < time())) {
            return error('该代金券已过期');
        } elseif ($card_info['status'] != 0) {
            return error('该代金券已被使用');
        } elseif (($card_info['related_cate'] && !in_array($store_cate, str2arr($card_info['related_cate'])))) {
            return error('该代金券不可用在该分类');
        } elseif ($user_id && ($user_id != $card_info['to_user'])) {
            return error('该代金券不在您的卡包');
        }
        return success($card_info->toArray(),'可用');

    }

    /**
     * @title 核销代金券（变为已使用）
     * @param int $card_id
     * @author FashionJune
     */
    public function destroyCard(int $card_id)
    {
        $update_data = [
            'used_time' => time(),//测试期间自动更新使用时间
            'destroy_time' => time(),
            'status' => -2,
        ];
        return $this->where('id', $card_id)->find()->save($update_data);
    }

}